#pragma once

#include <engine.core/XmlDomStream.hpp>
#include <engine.core/Logger.hpp>

#include "Reader.hpp"
#include "System.hpp"




/**
 * The DatabaseXmlReader implements the IDatabaseReader interface
 * to load the database (or simply a portion of it) from an xml file.
 *
 * Internally, it doesn't use QDomDocument (due to the massive memory
 * requirements, when the database is big), but sequentially goes through
 * the xml file by using QXmlStreamReader, which is much more efficient, but
 * more complex to use.
 */
class DatabaseXmlReader : public DatabaseReader
{
private:

	DatabaseSystemPtr    m_database;
	LoggerPtr            m_logger;

	QFile                m_file;
	QXmlStreamReader     m_reader;
	XmlDomReaderStream   m_xmlStream;

	ItemFactory          m_itemFactory;

public:

	/**
	 * Creates a new DatabaseXmlReader.
	 *
	 * @param fname         the filename of the xml document that should be read
	 * @param itemFactory   the factory that must be used to create all items
	 * @param logger        logger object that may be used to report errors/warnings
	 * @param database      database that must be used to implement inheritance (retrieve base-items)
	 */
	DatabaseXmlReader(const QString& fname, const ItemFactory& itemFactory, const LoggerPtr& logger, const DatabaseSystemPtr& database);
	virtual ~DatabaseXmlReader();



	/**
	 * This function simply reads the next item from the xml document and
	 * returns an empty DatabaseItemPtr, in case the document doesn't contain
	 * any more items.
	 */
	virtual LOOSE_PTR(DatabaseItem) read();



	/**
	 * That is a simply factory function that creates a new DatabasXmlReader.
	 * It's used by the DatabaseSystem to create instance of this reader.
	 */
	static DatabaseReaderPtr create(const QString& fname, const ItemFactory& itemFactory, const LoggerPtr& logger, const DatabaseSystemPtr& database);

private:

	/**
	 * Actual implementation to read the next DatabaseItem.
	 */
	LOOSE_PTR(DatabaseItem) readNext();

	/**
	 * Actual implementation to create t
	 */
	LOOSE_PTR(DatabaseItem) createItem(const QString& type, const QString& name, const DatabaseItem::Properties& data);

	/**
	 * Reads all properties from the current opened
	 * xml document.
	 */
	void readProperties(Properties& properties);
};
///////////////////////////////////////////////////////////////////////////////////////////////////
